#include "adc.h"


#if USE_ADC_0

/**
 * @desc  : 多通道 dma配置
 * @date  : 2024-11-29
 * @author: AnRui
 */
static void adc_0_dma_basic_cofig(uint16_t* adc_data_arr) {

    /******************ADC中DMA的配置***********************/
    // dma 开启只针对常规规则 在转换完自动触发dma转换 
    adc_dma_request_after_last_enable(ADC0);
    adc_dma_mode_enable(ADC0);
    /******************DMA 基础配置***********************/
    uint32_t dmax = DMA1;
    uint32_t dmax_rcu = RCU_DMA1;
    uint32_t dmax_ch = DMA_CH0;
    uint32_t damx_sub = DMA_SUBPERI0;
    // 方向: 外设到内存
    uint32_t dmax_dirction = DMA_PERIPH_TO_MEMORY;
    // dma 外设配置 
    uint32_t dmax_src = (uint32_t)(&ADC_RDATA(ADC0));
    uint32_t dmax_src_inc = DMA_PERIPH_INCREASE_DISABLE;
    uint32_t dmax_src_width = DMA_PERIPH_WIDTH_16BIT;
    uint32_t dmax_src_len = ADC0_NORMAL_CHANNEL_NUM;
    // 内存配置
    uint32_t dmax_dst = (uint32_t)(adc_data_arr);
    uint32_t dmax_dst_inc = DMA_MEMORY_INCREASE_ENABLE;

    /**************** DMA p2m *******************/
    // 时钟
    rcu_periph_clock_enable(dmax_rcu);
    // 重置dma
    // dma_deinit(dmax, dmax_ch);

    //////// dma 配置
    dma_single_data_parameter_struct dsdps;
    dma_single_data_para_struct_init(&dsdps);
    // 方向
    dsdps.direction = dmax_dirction;

    // 内存: dst
    dsdps.memory0_addr = dmax_dst;
    dsdps.memory_inc = dmax_dst_inc;

    // 外设: src
    dsdps.periph_addr = dmax_src;
    dsdps.periph_inc = dmax_src_inc;
    // 数据长度
    dsdps.number = dmax_src_len;
    // dst数据宽度
    dsdps.periph_memory_width = dmax_src_width;

    // 传输优先级
    dsdps.priority = DMA_PRIORITY_ULTRA_HIGH;

    // 循环模式  
    // 配置转换数据的长度为2  执行过程 : 触发拷贝 把数据复制到第一个数据的地址上
    // 再次触发拷贝 把数据复制到第2个数据的地址上 此时复制的次数达到设置
    // 再次触发拷贝 把数据复制到第1个数据的地址上 --->这就是循环的作用 回到初始位置
//    dsdps.circular_mode = DMA_CIRCULAR_MODE_ENABLE;
    dma_single_data_mode_init(dmax, dmax_ch, &dsdps);
    // 配置 dma 子连接
    dma_channel_subperipheral_select(dmax, dmax_ch, damx_sub);
    // 开启dma轮询
    dma_circulation_enable(dmax, dmax_ch);
    // 默认开启接收
    dma_flag_clear(dmax, dmax_ch, DMA_FLAG_FTF);
    dma_channel_enable(dmax, dmax_ch);
}

/**
 * @desc  : ADC0初始化配置
 * @date  : 2024-11-27
 * @author: AnRui
 */
void ADC_0_INIT(uint16_t* adc_data_arr) {
    // 1.配置时钟
    rcu_periph_clock_enable(RCU_ADC0);
    // 2.重置
    adc_deinit();
    // 3.配置主频
    adc_clock_config(ADC0_CLOCK_DIV);
    // 4.采样配置
    adc_resolution_config(ADC0, ADC0_RESOLUTION); // 分辨率
    adc_data_alignment_config(ADC0, ADC_DATAALIGN_RIGHT);// 数据右对齐
    // 5.规则配置
    ADC_CHANNEL_CONFIG();
    // 模式配置
    adc_special_function_config(ADC0, ADC_SCAN_MODE, ADC0_SCANMOD_ENABLE);// 扫描模式
    adc_special_function_config(ADC0, ADC_CONTINUOUS_MODE, ADC0_CONTINUOUS_ENABLE);//连续模式

    // 配置独立模式 避免adc0 adc1 之间相互影响
    adc_sync_mode_config(ADC_SYNC_MODE_INDEPENDENT);
    // GPIO外设配置
    ADC0_GPI0_CONFIG();
    // DMA外设配置
#if ADC0_DMA_ENABLE
    adc_0_dma_basic_cofig(adc_data_arr);
#endif
    // 打开ADC
    adc_enable(ADC0);
    // 校准ADC
    adc_calibration_enable(ADC0);
}

/**
 * @desc  : 触发adc常规通道转换
 * @date  : 2025-02-25
 * @author: AnRui
 * @note  :
 */
void ADC_0_routine_trigger() {
    // 触发常规通道转换
    adc_software_trigger_enable(ADC0, ADC_ROUTINE_CHANNEL);
}

/**
 * @desc  : 触发adc注入通道转换
 * @date  : 2025-02-25
 * @author: AnRui
 * @note  :
 */
void ADC_0_inserted_trigger() {
    // 触发注入通道转换
    adc_software_trigger_enable(ADC0, ADC_INSERTED_CHANNEL);
}

/**
 *  @desc  :获取注入规则通道数据
 * @date  : 2025-02-25
 * @author: AnRui
 * @param :  inserted_channel - {参数说明}:
 * @return: uint16_t
 * @note  :注入通道取值: ADC_INSERTED_CHANNEL_0|ADC_INSERTED_CHANNEL_1|ADC_INSERTED_CHANNEL_2|ADC_INSERTED_CHANNEL_3
 */
uint16_t  ADC_inserted_channel_result(uint8_t inserted_channel) {
    return adc_inserted_data_read(ADC0, inserted_channel);
}

#endif 